﻿using SdmxMl.Common;
using SdmxMl.Excel;
using SdmxMl.Structure;

namespace SasPlugIn.DB
{
    public class CodelistTable : DbTable
    {
        /// <summary>The artefact to transform in SAS instructions for table creation</summary>
        private CodeListType clt;

        /// <summary>The text format to apply for codes</summary>
        private TextFormatType tftCode;
        
        /// <summary>
        /// C'tor for generation of a SAS table holding codelists artefact Information
        /// </summary>
        /// <param name="codelistArtefact">an object of Artefact type</param>
        /// <param name="anInv">inventory of selected annotations to place in table</param>
        /// <param name="formatCode">The text format to apply for codes</param>
        /// <param name="tableName">Name of DB table</param>
        /// <param name="prefix">Prefix for DB table</param>
        public CodelistTable(CodeListType codelistArtefact, TextFormatType formatCode, AnnotationInventory anInv, string tableName, string prefix)
            : base(codelistArtefact, anInv, tableName, prefix)
        {
            tftCode = formatCode;
            Create();
        }

        /// <summary>
        /// Fill Header columns according to artefact attributes
        /// </summary>
        protected override void CreateColumns()
        {
            clt = artefact as CodeListType;
            if (tftCode == null)
                tftCode = clt.GetDefaultTextFormat();
            TextFormatType tftLevel = new TextFormatType();
            tftLevel.TextType = TextTypeType.Integer;
            tftLevel.maxLength = "2";

            columns.Add(new DbColumn(CODE_COL_NAME, tftCode));
            columns.Add(new DbColumn(PARENT_COL_NAME, tftCode));
            columns.Add(new DbColumn(LEVEL_COL_NAME, tftLevel));

            foreach (string lg in LangSupport.SupportedLanguages)
                columns.Add(new DbColumn(INTERNATIONALIZED_NAME_PREFIX + lg, NAME_DEFAULT_LEN));

            foreach (string lg in LangSupport.SupportedLanguages)
                columns.Add(new DbColumn(INTERNATIONALIZED_DESCR_PREFIX + lg, DESCRIPTION_DEFAULT_LEN));

            // here Annotations selected
            GenAnnotationColumns();
        }

        protected override void FillData()
        {
            foreach (CodeType c in clt.CodeList)
            {
                // Prepare row value list
                RowValues rowValues = new RowValues(columns.Count);
                rowValues.Add(c.Id);
                rowValues.Add(c.Parent);
                rowValues.Add(GetLevelOfCode(clt, c.Id).ToString());

                foreach (string lg in LangSupport.SupportedLanguages)
                {
                    rowValues.Add(c.Name.GetForLanguage(lg));
                }

                foreach (string lg in LangSupport.SupportedLanguages)
                {
                    rowValues.Add(c.Description.GetForLanguage(lg));
                }

                // Annotations
                AddAnnotations(rowValues, c.AnnotationList);

                // Add row of data
                AddRowData(rowValues);
            }

        }

        /// <summary>
        /// Determines level of given code if codelist has hierarchy
        /// </summary>
        /// <param name="clt">Codelist</param>
        /// <param name="code">code value</param>
        /// <returns>level starting at 1 / 0 means code not found</returns>
        private int GetLevelOfCode(CodeListType clt, string code)
        {
            int level = 0;
            CodeType c = clt.CodeList.LocateItem(code) as CodeType;
            do
            {
                if (c != null)
                {
                    ++level;
                    c = clt.CodeList.LocateItem(c.Parent) as CodeType;
                }
            } while (c != null);

            return level;
        }

    }
}
